<!DOCTYPE html>
<html style="display: none;" lang="zh">
    <head>
    <meta charset="utf-8">
    <!--
        © Material Theme
        https://github.com/viosey/hexo-theme-material
        Version: 1.5.2 -->
    <script>
        window.materialVersion = "1.5.2"
        // Delete localstorage with these tags
        window.oldVersion = [
            'codestartv1',
            '1.3.4',
            '1.4.0',
            '1.4.0b1',
            '1.5.0'
        ]
    </script>

    <!-- dns prefetch -->
    <meta http-equiv="x-dns-prefetch-control" content="on">


    <link rel="dns-prefetch" href="https://cdn1.lncld.net"/>













    <!-- Meta & Info -->
    <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
    <meta name="renderer" content="webkit">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">

    <!-- Title -->
    
    <title>
        
            HashMap源码分析 | 
        
        android开发者
    </title>

    <!-- Favicons -->
    <link rel="icon shortcut" type="image/ico" href="/img/favicon.png">
    <link rel="icon" href="/img/favicon.png">

    <meta name="format-detection" content="telephone=no"/>
    <meta name="description" itemprop="description" content="android开发工程师，学习，记录。">
    <meta name="keywords" content="android,java,源码">
    <meta name="theme-color" content="#0097A7">

    <!-- Disable Fucking Bloody Baidu Tranformation -->
    <meta http-equiv="Cache-Control" content="no-transform" />
    <meta http-equiv="Cache-Control" content="no-siteapp" />

    <!--[if lte IE 9]>
        <link rel="stylesheet" href="/css/ie-blocker.css">

        
            <script src="/js/ie-blocker.zhCN.js"></script>
        
    <![endif]-->

    <!-- Import lsloader -->
    <script>(function(){window.lsloader={jsRunSequence:[],jsnamemap:{},cssnamemap:{}};lsloader.removeLS=function(a){try{localStorage.removeItem(a)}catch(b){}};lsloader.setLS=function(a,c){try{localStorage.setItem(a,c)}catch(b){}};lsloader.getLS=function(a){var c="";try{c=localStorage.getItem(a)}catch(b){c=""}return c};versionString="/*"+(window.materialVersion||"unknownVersion")+"*/";lsloader.clean=function(){try{var b=[];for(var a=0;a<localStorage.length;a++){b.push(localStorage.key(a))}b.forEach(function(e){var f=lsloader.getLS(e);if(window.oldVersion){var d=window.oldVersion.reduce(function(g,h){return g||f.indexOf("/*"+h+"*/")!==-1},false);if(d){lsloader.removeLS(e)}}})}catch(c){}};lsloader.clean();lsloader.load=function(f,a,b,d){if(typeof b==="boolean"){d=b;b=undefined}d=d||false;b=b||function(){};var e;e=this.getLS(f);if(e&&e.indexOf(versionString)===-1){this.removeLS(f);this.requestResource(f,a,b,d);return}if(e){var c=e.split(versionString)[0];if(c!=a){console.log("reload:"+a);this.removeLS(f);this.requestResource(f,a,b,d);return}e=e.split(versionString)[1];if(d){this.jsRunSequence.push({name:f,code:e});this.runjs(a,f,e)}else{document.getElementById(f).appendChild(document.createTextNode(e));b()}}else{this.requestResource(f,a,b,d)}};lsloader.requestResource=function(b,e,a,c){var d=this;if(c){this.iojs(e,b,function(h,f,g){d.setLS(f,h+versionString+g);d.runjs(h,f,g)})}else{this.iocss(e,b,function(f){document.getElementById(b).appendChild(document.createTextNode(f));d.setLS(b,e+versionString+f)},a)}};lsloader.iojs=function(d,b,g){var a=this;a.jsRunSequence.push({name:b,code:""});try{var f=new XMLHttpRequest();f.open("get",d,true);f.onreadystatechange=function(){if(f.readyState==4){if((f.status>=200&&f.status<300)||f.status==304){if(f.response!=""){g(d,b,f.response);return}}a.jsfallback(d,b)}};f.send(null)}catch(c){a.jsfallback(d,b)}};lsloader.iocss=function(f,c,h,a){var b=this;try{var g=new XMLHttpRequest();g.open("get",f,true);g.onreadystatechange=function(){if(g.readyState==4){if((g.status>=200&&g.status<300)||g.status==304){if(g.response!=""){h(g.response);a();return}}b.cssfallback(f,c,a)}};g.send(null)}catch(d){b.cssfallback(f,c,a)}};lsloader.iofonts=function(f,c,h,a){var b=this;try{var g=new XMLHttpRequest();g.open("get",f,true);g.onreadystatechange=function(){if(g.readyState==4){if((g.status>=200&&g.status<300)||g.status==304){if(g.response!=""){h(g.response);a();return}}b.cssfallback(f,c,a)}};g.send(null)}catch(d){b.cssfallback(f,c,a)}};lsloader.runjs=function(f,c,e){if(!!c&&!!e){for(var b in this.jsRunSequence){if(this.jsRunSequence[b].name==c){this.jsRunSequence[b].code=e}}}if(!!this.jsRunSequence[0]&&!!this.jsRunSequence[0].code&&this.jsRunSequence[0].status!="failed"){var a=document.createElement("script");a.appendChild(document.createTextNode(this.jsRunSequence[0].code));a.type="text/javascript";document.getElementsByTagName("head")[0].appendChild(a);this.jsRunSequence.shift();if(this.jsRunSequence.length>0){this.runjs()}}else{if(!!this.jsRunSequence[0]&&this.jsRunSequence[0].status=="failed"){var d=this;var a=document.createElement("script");a.src=this.jsRunSequence[0].path;a.type="text/javascript";this.jsRunSequence[0].status="loading";a.onload=function(){d.jsRunSequence.shift();if(d.jsRunSequence.length>0){d.runjs()}};document.body.appendChild(a)}}};lsloader.tagLoad=function(b,a){this.jsRunSequence.push({name:a,code:"",path:b,status:"failed"});this.runjs()};lsloader.jsfallback=function(c,b){if(!!this.jsnamemap[b]){return}else{this.jsnamemap[b]=b}for(var a in this.jsRunSequence){if(this.jsRunSequence[a].name==b){this.jsRunSequence[a].code="";this.jsRunSequence[a].status="failed";this.jsRunSequence[a].path=c}}this.runjs()};lsloader.cssfallback=function(e,c,b){if(!!this.cssnamemap[c]){return}else{this.cssnamemap[c]=1}var d=document.createElement("link");d.type="text/css";d.href=e;d.rel="stylesheet";d.onload=d.onerror=b;var a=document.getElementsByTagName("script")[0];a.parentNode.insertBefore(d,a)};lsloader.runInlineScript=function(c,b){var a=document.getElementById(b).innerText;this.jsRunSequence.push({name:c,code:a});this.runjs()}})();</script>

    <!-- Import queue -->
    <script>function Queue(){this.dataStore=[];this.offer=b;this.poll=d;this.execNext=a;this.debug=false;this.startDebug=c;function b(e){if(this.debug){console.log("Offered a Queued Function.")}if(typeof e==="function"){this.dataStore.push(e)}else{console.log("You must offer a function.")}}function d(){if(this.debug){console.log("Polled a Queued Function.")}return this.dataStore.shift()}function a(){var e=this.poll();if(e!==undefined){if(this.debug){console.log("Run a Queued Function.")}e()}}function c(){this.debug=true}}var queue=new Queue();</script>

    <!-- Import CSS -->
    
        <style id="material_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("material_css","/css/material.min.css?Z7a72R1E4SxzBKR/WGctOA==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>
        <style id="style_css"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("style_css","/css/style.min.css?NKhlKQkXw/c66TR5p4wO+w==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>

        

    

    

    <!-- Config CSS -->

<!-- Other Styles -->
<style>
  body, html {
    font-family: Roboto, "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
    overflow-x: hidden !important;
  }
  
  code {
    font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
  }

  a {
    color: #00838F;
  }

  .mdl-card__media,
  #search-label,
  #search-form-label:after,
  #scheme-Paradox .hot_tags-count,
  #scheme-Paradox .sidebar_archives-count,
  #scheme-Paradox .sidebar-colored .sidebar-header,
  #scheme-Paradox .sidebar-colored .sidebar-badge{
    background-color: #0097A7 !important;
  }

  /* Sidebar User Drop Down Menu Text Color */
  #scheme-Paradox .sidebar-colored .sidebar-nav>.dropdown>.dropdown-menu>li>a:hover,
  #scheme-Paradox .sidebar-colored .sidebar-nav>.dropdown>.dropdown-menu>li>a:focus {
    color: #0097A7 !important;
  }

  #post_entry-right-info,
  .sidebar-colored .sidebar-nav li:hover > a,
  .sidebar-colored .sidebar-nav li:hover > a i,
  .sidebar-colored .sidebar-nav li > a:hover,
  .sidebar-colored .sidebar-nav li > a:hover i,
  .sidebar-colored .sidebar-nav li > a:focus i,
  .sidebar-colored .sidebar-nav > .open > a,
  .sidebar-colored .sidebar-nav > .open > a:hover,
  .sidebar-colored .sidebar-nav > .open > a:focus,
  #ds-reset #ds-ctx .ds-ctx-entry .ds-ctx-head a {
    color: #0097A7 !important;
  }

  .toTop {
    background: #757575 !important;
  }

  .material-layout .material-post>.material-nav,
  .material-layout .material-index>.material-nav,
  .material-nav a {
    color: #757575;
  }

  #scheme-Paradox .MD-burger-layer {
    background-color: #757575;
  }

  #scheme-Paradox #post-toc-trigger-btn {
    color: #757575;
  }

  .post-toc a:hover {
    color: #00838F;
    text-decoration: underline;
  }

</style>


<!-- Theme Background Related-->

    <style>
      body{
        background-color: #F5F5F5;
      }

      /* blog_info bottom background */
      #scheme-Paradox .material-layout .something-else .mdl-card__supporting-text{
        background-color: #fff;
      }
    </style>




<!-- Fade Effect -->

    <style>
      .fade {
        transition: all 800ms linear;
        -webkit-transform: translate3d(0,0,0);
        -moz-transform: translate3d(0,0,0);
        -ms-transform: translate3d(0,0,0);
        -o-transform: translate3d(0,0,0);
        transform: translate3d(0,0,0);
        opacity: 1;
      }

      .fade.out{
        opacity: 0;
      }
    </style>


<!-- Import Font -->
<!-- Import Roboto -->

    <link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500" rel="stylesheet">


<!-- Import Material Icons -->


    <style id="material_icons"></style><script>if(typeof window.lsLoadCSSMaxNums === "undefined")window.lsLoadCSSMaxNums = 0;window.lsLoadCSSMaxNums++;lsloader.load("material_icons","/css/material-icons.css?pqhB/Rd/ab0H2+kZp0RDmw==",function(){if(typeof window.lsLoadCSSNums === "undefined")window.lsLoadCSSNums = 0;window.lsLoadCSSNums++;if(window.lsLoadCSSNums == window.lsLoadCSSMaxNums)document.documentElement.style.display="";}, false)</script>




    <!-- Import jQuery -->
    
        <script>lsloader.load("jq_js","/js/jquery.min.js?qcusAULNeBksqffqUM2+Ig==", true)</script>
    

    <!-- WebAPP Icons -->
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="application-name" content="android开发者">
    <meta name="msapplication-starturl" content="http://www.xincc.top/2016/01/01/java/HashMap源码分析/">
    <meta name="msapplication-navbutton-color" content="#0097A7">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-title" content="android开发者">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <link rel="apple-touch-icon" href="/img/favicon.png">

    <!-- Site Verification -->
    
    

    <!-- RSS -->
    

    <!-- The Open Graph protocol -->
    <meta property="og:url" content="http://www.xincc.top/2016/01/01/java/HashMap源码分析/">
    <meta property="og:type" content="blog">
    <meta property="og:title" content="HashMap源码分析 | android开发者">
    <meta property="og:image" content="/img/favicon.png">
    <meta property="og:description" content="android开发工程师，学习，记录。">
    <meta property="og:article:tag" content="java"> <meta property="og:article:tag" content="源码"> 

    
        <meta property="article:published_time" content="Fri Jan 01 2016 03:00:34 GMT+0800">
        <meta property="article:modified_time" content="Sun May 06 2018 16:42:00 GMT+0800">
    

    <!-- The Twitter Card protocol -->
    <meta name="twitter:card" content="summary_large_image">

    <!-- Add canonical link for SEO -->
    
        <link rel="canonical" href="http://www.xincc.top/2016/01/01/java/HashMap源码分析/index.html" />
    

    <!-- Structured-data for SEO -->
    
        


<script type="application/ld+json">
{
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "mainEntityOfPage": "http://www.xincc.top/2016/01/01/java/HashMap源码分析/index.html",
    "headline": "HashMap源码分析",
    "datePublished": "Fri Jan 01 2016 03:00:34 GMT+0800",
    "dateModified": "Sun May 06 2018 16:42:00 GMT+0800",
    "author": {
        "@type": "Person",
        "name": "xinwii",
        "image": {
            "@type": "ImageObject",
            "url": "/img/avatar.png"
        },
        "description": "Hi, nice to meet you"
    },
    "publisher": {
        "@type": "Organization",
        "name": "android开发者",
        "logo": {
            "@type":"ImageObject",
            "url": "/img/favicon.png"
        }
    },
    "keywords": ",java,源码android",
    "description": "android开发工程师，学习，记录。",
}
</script>


    

    <!-- Analytics -->
    
    
        <script>
    var _hmt = _hmt || [];
    (function() {var hm = document.createElement('script');
    hm.src = 'https://hm.baidu.com/hm.js?ee8e425850499b806260824b0147ff70';
    var s = document.getElementsByTagName('script')[0];
    s.parentNode.insertBefore(hm, s);
    })();
</script>
    
    

    <!-- Custom Head -->
    

</head>


    
        <body id="scheme-Paradox" class="lazy">
            <div class="material-layout  mdl-js-layout has-drawer is-upgraded">
                

                <!-- Main Container -->
                <main class="material-layout__content" id="main">

                    <!-- Top Anchor -->
                    <div id="top"></div>

                    
                        <!-- Hamburger Button -->
                        <button class="MD-burger-icon sidebar-toggle">
                            <span class="MD-burger-layer"></span>
                        </button>
                    

                    <!-- Post TOC -->

    
    <!-- Back Button -->
    <!--
    <div class="material-back" id="backhome-div" tabindex="0">
        <a class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon"
           href="#" onclick="window.history.back();return false;"
           target="_self"
           role="button"
           data-upgraded=",MaterialButton,MaterialRipple">
            <i class="material-icons" role="presentation">arrow_back</i>
            <span class="mdl-button__ripple-container">
                <span class="mdl-ripple"></span>
            </span>
        </a>
    </div>
    -->


    <!-- Left aligned menu below button -->
    
    
    <button id="post-toc-trigger-btn"
        class="mdl-button mdl-js-button mdl-button--icon">
        <i class="material-icons">format_list_numbered</i>
    </button>

    <ul class="post-toc-wrap mdl-menu mdl-menu--bottom-left mdl-js-menu mdl-js-ripple-effect" for="post-toc-trigger-btn" style="max-height:80vh; overflow-y:scroll;">
        <ol class="post-toc"><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#HashMap源码分析"><span class="post-toc-number">1.</span> <span class="post-toc-text">HashMap源码分析</span></a></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#1-HashMap简介"><span class="post-toc-number">2.</span> <span class="post-toc-text">1. HashMap简介</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#1-1-结构"><span class="post-toc-number">2.1.</span> <span class="post-toc-text">1.1 结构</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#1-2-hash算法"><span class="post-toc-number">2.2.</span> <span class="post-toc-text">1.2 hash算法</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#1-3-hashCode和equals"><span class="post-toc-number">2.3.</span> <span class="post-toc-text">1.3 hashCode和equals</span></a></li></ol></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#2-HashMap分析"><span class="post-toc-number">3.</span> <span class="post-toc-text">2. HashMap分析</span></a><ol class="post-toc-child"><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-1-关键属性"><span class="post-toc-number">3.1.</span> <span class="post-toc-text">2.1 关键属性</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-2-构造函数"><span class="post-toc-number">3.2.</span> <span class="post-toc-text">2.2 构造函数</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-3-put-K-key-V-value"><span class="post-toc-number">3.3.</span> <span class="post-toc-text">2.3 put(K key, V value)</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-4-get-Object-key"><span class="post-toc-number">3.4.</span> <span class="post-toc-text">2.4 get(Object key)</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-5-remove-Object-key"><span class="post-toc-number">3.5.</span> <span class="post-toc-text">2.5 remove(Object key)</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-6-Set-lt-Map-Entry-lt-K-V-gt-gt-entrySet"><span class="post-toc-number">3.6.</span> <span class="post-toc-text">2.6 Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet()</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-7-Set-lt-K-gt-keySet"><span class="post-toc-number">3.7.</span> <span class="post-toc-text">2.7 Set&lt;K&gt; keySet()</span></a></li><li class="post-toc-item post-toc-level-2"><a class="post-toc-link" href="#2-8-杂鱼方法"><span class="post-toc-number">3.8.</span> <span class="post-toc-text">2.8 杂鱼方法</span></a></li></ol></li><li class="post-toc-item post-toc-level-1"><a class="post-toc-link" href="#3-总结"><span class="post-toc-number">4.</span> <span class="post-toc-text">3. 总结</span></a></li></ol>
    </ul>
    




<!-- Layouts -->

    <!-- Post Module -->
    <div class="material-post_container">

        <div class="material-post mdl-grid">
            <div class="mdl-card mdl-shadow--4dp mdl-cell mdl-cell--12-col">

                <!-- Post Header(Thumbnail & Title) -->
                
    <!-- Paradox Post Header -->
    
        
            <!-- Random Thumbnail -->
            <div class="post_thumbnail-random mdl-card__media mdl-color-text--grey-50">
            <script type="text/ls-javascript" id="post-thumbnail-script">
    var randomNum = Math.floor(Math.random() * 19 + 1);

    $('.post_thumbnail-random').attr('data-original', '/img/random/material-' + randomNum + '.png');
    $('.post_thumbnail-random').addClass('lazy');
</script>

        
    
            <p class="article-headline-p">
                HashMap源码分析
            </p>
        </div>





                
                    <!-- Paradox Post Info -->
                    <div class="mdl-color-text--grey-700 mdl-card__supporting-text meta">

    <!-- Author Avatar -->
    <div id="author-avatar">
        <img src="/img/avatar.png" width="44px" height="44px" alt="Author Avatar"/>
    </div>
    <!-- Author Name & Date -->
    <div>
        <strong>xinwii</strong>
        <span>1月 01, 2016</span>
    </div>

    <div class="section-spacer"></div>

    <!-- Favorite -->
    <!--
        <button id="article-functions-like-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon btn-like">
            <i class="material-icons" role="presentation">favorite</i>
            <span class="visuallyhidden">favorites</span>
        </button>
    -->

    <!-- Qrcode -->
    

    <!-- Tags (bookmark) -->
    
    <button id="article-functions-viewtags-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
        <i class="material-icons" role="presentation">bookmark</i>
        <span class="visuallyhidden">bookmark</span>
    </button>
    <ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-functions-viewtags-button">
        <li class="mdl-menu__item">
        <a class="post_tag-link" href="/tags/java/">java</a></li><li class="mdl-menu__item"><a class="post_tag-link" href="/tags/源码/">源码</a>
    </ul>
    

    <!-- Share -->
    
        <button id="article-fuctions-share-button" class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon">
    <i class="material-icons" role="presentation">share</i>
    <span class="visuallyhidden">share</span>
</button>
<ul class="mdl-menu mdl-menu--bottom-right mdl-js-menu mdl-js-ripple-effect" for="article-fuctions-share-button">
    
    <!-- Leancloud Views -->
        <a class="post_share-link" href="#">
            <li class="mdl-menu__item">
                <span id="/2016/01/01/java/HashMap源码分析/" class="leancloud-views_num" data-flag-title="HashMap源码分析">
     &nbsp;浏览量
</span>

            </li>
        </a>
    

    

    <!-- Share Weibo -->
    
        <a class="post_share-link" href="http://service.weibo.com/share/share.php?appkey=&title=HashMap源码分析&url=http://www.xincc.top/2016/01/01/java/HashMap源码分析/index.html&pic=http://www.xincc.top/img/favicon.png&searchPic=false&style=simple" target="_blank">
            <li class="mdl-menu__item">
                分享到微博
            </li>
        </a>
    

    <!-- Share Twitter -->
    
        <a class="post_share-link" href="https://twitter.com/intent/tweet?text=HashMap源码分析&url=http://www.xincc.top/2016/01/01/java/HashMap源码分析/index.html&via=xinwii" target="_blank">
            <li class="mdl-menu__item">
                分享到 Twitter
            </li>
        </a>
    

    <!-- Share Facebook -->
    
        <a class="post_share-link" href="https://www.facebook.com/sharer/sharer.php?u=http://www.xincc.top/2016/01/01/java/HashMap源码分析/index.html" target="_blank">
            <li class="mdl-menu__item">
                分享到 Facebook
            </li>
        </a>
    

    <!-- Share Google+ -->
    
        <a class="post_share-link" href="https://plus.google.com/share?url=http://www.xincc.top/2016/01/01/java/HashMap源码分析/index.html" target="_blank">
            <li class="mdl-menu__item">
                分享到 Google+
            </li>
        </a>
    

    <!-- Share LinkedIn -->
    

    <!-- Share QQ -->
    

    <!-- Share Telegram -->
    
</ul>

    
</div>

                

                <!-- Post Content -->
                <div id="post-content" class="mdl-color-text--grey-700 mdl-card__supporting-text fade out">
    
        <p>[TOC]</p>
<h1 id="HashMap源码分析"><a href="#HashMap源码分析" class="headerlink" title="HashMap源码分析"></a>HashMap源码分析</h1><p>HashMap类的源码分析,本文是基于 <code>java1.6</code> 和 <code>java1.7</code> 的源码。HashMap 是基于哈希表的Map接口的实现，主要用来提供键和值的映射操作，并且键值不能<strong>“重复”</strong>，且<strong>无序</strong>。java6和7 两个版本中如果有明显不同，我会明确标出。</p>
<h1 id="1-HashMap简介"><a href="#1-HashMap简介" class="headerlink" title="1. HashMap简介"></a>1. HashMap简介</h1><h2 id="1-1-结构"><a href="#1-1-结构" class="headerlink" title="1.1 结构"></a>1.1 结构</h2><p>HashMap存储结构图：<br><img src="http://img.blog.csdn.net/20151226170102717" alt=""><br>从图中可以看出HashMap结合了<code>数组</code>和<code>链表</code>两种数据结构，众所周知</p>
<ul>
<li><ol>
<li>数组在检索的速度快，插入和删除的速度慢</li>
</ol>
</li>
<li><ol start="2">
<li>链表在插入和删除的速度快，检索的速度慢</li>
</ol>
</li>
</ul>
<blockquote>
<p><code>这样在取长补短的情况下产生了哈希散列表的存储方式</code></p>
</blockquote>
<p>图中，最左边竖着的存储结构是数组，每一个格子维护一个链表，这些格子叫做 <strong><code>桶</code></strong> 。每个链表的节点在java中是一个 Entry类，维护者一对键和值。这个看起来就像将一个大的链表拆分成多个小的链表，然后将每个小链表的头放在数组中一样，至于数据应该放入在哪一个桶中那就要根据对象的 <code>hash 值</code>来进行计算了。</p>
<h2 id="1-2-hash算法"><a href="#1-2-hash算法" class="headerlink" title="1.2 hash算法"></a>1.2 hash算法</h2><p>那么算出<code>hash值（散列码）</code>的算法就是hash算法, 由于我们需要将对象（而对象包括很多，比如数字，字符，类等等）存放到每个桶中, 那么就需要计算出一个整数，然后<strong><code>与桶的数量进行模运算(HashMap中不是采用取模运算)</code></strong>才能确定处于哪一个桶之中。那么hash算法的目的就是将这些不统一的对象统一算出一个整数(int型)。<br>    优秀的hash算法需要从时间，空间和散列程度等等进行考虑，那么关于算法就不多多说明了。提供一个下载地址，自行研究</p>
<p>///////////////////////<br><a href="http://download.csdn.net/detail/u013082133/9378254" target="_blank" rel="noopener">http://download.csdn.net/detail/u013082133/9378254</a><br>///////////////////////<br>下面看看hashMap中的hash算法，1.6和1.7中的关键部分基本相同   </p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 1.6, 传入的 h 是某个对象o的hashCode()方法后的值, 进行了二次散列</span></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">hash</span><span class="params">(<span class="keyword">int</span> h)</span> </span>&#123;</span><br><span class="line">    h ^= (h &gt;&gt;&gt; <span class="number">20</span>) ^ (h &gt;&gt;&gt; <span class="number">12</span>);</span><br><span class="line">    <span class="keyword">return</span> h ^ (h &gt;&gt;&gt; <span class="number">7</span>) ^ (h &gt;&gt;&gt; <span class="number">4</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 1.7, hashSeed默认是0, 这里仅仅多了对string的处理</span></span><br><span class="line"><span class="function"><span class="keyword">final</span> <span class="keyword">int</span> <span class="title">hash</span><span class="params">(Object k)</span> </span>&#123;                                           </span><br><span class="line">    <span class="keyword">int</span> h = hashSeed;                                                </span><br><span class="line">    <span class="keyword">if</span> (<span class="number">0</span> != h &amp;&amp; k <span class="keyword">instanceof</span> String) &#123;                             </span><br><span class="line">        <span class="keyword">return</span> sun.misc.Hashing.stringHash32((String) k);            </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 同样进行的二次散列                                                      </span></span><br><span class="line">    h ^= k.hashCode();</span><br><span class="line">    h ^= (h &gt;&gt;&gt; <span class="number">20</span>) ^ (h &gt;&gt;&gt; <span class="number">12</span>);</span><br><span class="line">    <span class="keyword">return</span> h ^ (h &gt;&gt;&gt; <span class="number">7</span>) ^ (h &gt;&gt;&gt; <span class="number">4</span>);                                </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<h2 id="1-3-hashCode和equals"><a href="#1-3-hashCode和equals" class="headerlink" title="1.3 hashCode和equals"></a>1.3 hashCode和equals</h2><p>说完hash算法之后，还有一个问题就是如果最后算出来的两个对象在<code>同一个桶中</code>（hashCode相同或者最后的取模相同），那该如何处理（这种现象称为<strong><code>散列冲突</code></strong>）。此时就需要每个对象的<code>equals方法</code>出场了，所以这也是java建议在覆盖hashCode()方法同时也覆盖一下equals方法的原因。当两个对象放生散列冲突的时候，这个时候就要将该桶中链表中每个元素用equals进行比较，如果为true，那么就覆盖该元素，否则挂到链表的后面。</p>
<h1 id="2-HashMap分析"><a href="#2-HashMap分析" class="headerlink" title="2. HashMap分析"></a>2. HashMap分析</h1><h2 id="2-1-关键属性"><a href="#2-1-关键属性" class="headerlink" title="2.1 关键属性"></a>2.1 关键属性</h2><p>java1.6和1.7的属性基本一样，1.7中就多了一个空数组的定义。这个是一个性能的改善吧，就像之前ArrayList类中一样，1.6在初始化实例的就会把默认的容量直接赋值给数组；而在1.7后初始化实例的时候只会赋值一个空的数组，直到调用添加方法的时候才会去初始化容量。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">// 1.6</span><br><span class="line">static final int DEFAULT_INITIAL_CAPACITY = 16; // 默认容量</span><br><span class="line">static final int MAXIMUM_CAPACITY = 1 &lt;&lt; 30;    // 默认最大容量</span><br><span class="line">static final float DEFAULT_LOAD_FACTOR = 0.75f; // 默认负载因子</span><br><span class="line">transient Entry[] table; // 链表数组</span><br><span class="line">transient int size; // 实际数量</span><br><span class="line">int threshold;      // 容量的临界值</span><br><span class="line">final float loadFactor; //负载因子</span><br><span class="line">transient volatile int modCount;   // 修改次数</span><br><span class="line">// 1.7      </span><br><span class="line">static final int DEFAULT_INITIAL_CAPACITY = 1 &lt;&lt; 4; // aka 16</span><br><span class="line">static final int MAXIMUM_CAPACITY = 1 &lt;&lt; 30;</span><br><span class="line">static final float DEFAULT_LOAD_FACTOR = 0.75f;</span><br><span class="line">static final Entry&lt;?,?&gt;[] EMPTY_TABLE = &#123;&#125;;</span><br><span class="line">transient Entry&lt;K,V&gt;[] table = (Entry&lt;K,V&gt;[]) EMPTY_TABLE;</span><br><span class="line">transient int size;</span><br><span class="line">int threshold;</span><br><span class="line">final float loadFactor;                                                               </span><br><span class="line">transient int modCount;</span><br></pre></td></tr></table></figure>
<p>其次这里也对这个负载因子做一下说明：负载因子是<code>容量和临界值的商</code>，对于HashMap的检索性能其实是和<code>容量</code>，<code>hash算法</code>以及<code>数据的数量</code>有一定的关系。</p>
<ol>
<li>如果数组容量为1，那么基本和单链表一模一样。</li>
<li>如果容量过大，每个桶只放一个Entry，那么和普通的数组又基本一致。</li>
<li>好的hash算法可以使得数据有更好的分散性</li>
</ol>
<p>其次负载因子是数组容量进行扩容的一个依据，如果当临界值超过了负载值，那么就会对数组的容量进行扩容，一般扩容的大小是上一次的2倍。负载因子也是时间和空间的一种平衡，一般采用jdk的默认0.75f就好了。</p>
<h2 id="2-2-构造函数"><a href="#2-2-构造函数" class="headerlink" title="2.2 构造函数"></a>2.2 构造函数</h2><p>java1.6中调用了默认构造函数之后，会初始化负载因子，临界值和链表数组</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">public HashMap() &#123;</span><br><span class="line">     this.loadFactor = DEFAULT_LOAD_FACTOR; // 0.75f</span><br><span class="line">     threshold = (int)(DEFAULT_INITIAL_CAPACITY * DEFAULT_LOAD_FACTOR); // 16 * 0.75 = 12</span><br><span class="line">     table = new Entry[DEFAULT_INITIAL_CAPACITY]; // 链表数组大小16</span><br><span class="line">     init();  // 空的函数, 估计为以后java版本更新提供                                                         </span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>
<p>而在1.7中，临界值和链表数组大小都是在调用了put方法之后进行初始化的<br>注意：要是调用了其他构造方法，如自己传入一个默认的容量，那么java会寻找这个数字的最近2次幂来作为默认容量</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// Find a power of 2 &gt;= initialCapacity</span><br><span class="line">int capacity = 1;</span><br><span class="line">while (capacity &lt; initialCapacity)</span><br><span class="line">    capacity &lt;&lt;= 1;</span><br></pre></td></tr></table></figure>
<h2 id="2-3-put-K-key-V-value"><a href="#2-3-put-K-key-V-value" class="headerlink" title="2.3 put(K key, V value)"></a>2.3 put(K key, V value)</h2><p>1.6和1.7的两个方法基本一样，除了1.7中多了个初始化。</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// 1.7中的 inflateTable 与1.6的初始化过程基本类似</span><br><span class="line">if (table == EMPTY_TABLE) &#123;</span><br><span class="line">    inflateTable(threshold);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>下面说一下put方法的逻辑：</p>
<ul>
<li><code>1. 插入null键</code></li>
</ul>
<p>（首先这个是与HashTable的一个区别，HashMap支持key为null, 当然HashTable也不支持null值）<br>null键的这个Entry是插入在table(链表数组的0下标位置)，代码是先判断该链表上有没有null键对应的Entry，如果有就替换，否则<strong><code>添加到链表头</code></strong>。<br><img src="http://img.blog.csdn.net/20151226170725146" alt=""><br>addEntry(…)方法中，做了两个操作：1. 添加数据（这里是添加到链表头），2. 是否扩容（扩容的大小是上次的两倍）<br>这里数据的添加是将当前数据作为链表的头，然后将当前Entry的下一个指针指向原先的头。<br>这里扩容的判断上面java1.6和1.7又有点不一样，1.7中多了对当前桶的头Entry进行null判断。这就会导致在1.6中如果默认情况下，当前的size大于了临界值就会对数组进行扩容，但是在1.7中如果当前桶的头Entry不是null的情况下才会进行扩容(后来看了下java8的源码，在判断上面又把1.7多余的这个null判断取消掉了。。。无语中)。反正不管怎么样，肯定是要根据当前实际size和临界值threshold的大小进行数组的扩容的。<br>这里建议大家去读一读这里的源代码，就不黏贴了。。在这里的Entry拷贝上面进行的判断和内存的释放逻辑上简直让我觉得代码写的好严谨。。。</p>
<ul>
<li><code>2. 插入非null键</code></li>
</ul>
<p>首先算出hash值（HashMap的hash算法在上面黏贴了），然后在求出所在桶的索引位置</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 根据求出的hash值和数组容量大小-1进行与运算, 保证返回值始终小于length-1</span></span><br><span class="line"><span class="comment">// 这里讲下HashTable中的实现是采用取模运算的, 没有这种位运算效率高</span></span><br><span class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">int</span> <span class="title">indexFor</span><span class="params">(<span class="keyword">int</span> h, <span class="keyword">int</span> length)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">return</span> h &amp; (length-<span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>然后下面的处理就跟null键插入的逻辑基本一样，这里应该注意一个设计思想，就是大家在以后替换某个元素的时候，记得把旧的元素返回出去，以防止被调用者使用。<br>putAll()也没啥好讲的，基本就是扩容的区别上，其次就是将数据一个个调用put()方法。</p>
<h2 id="2-4-get-Object-key"><a href="#2-4-get-Object-key" class="headerlink" title="2.4 get(Object key)"></a>2.4 get(Object key)</h2><p>这里get方法同样也分为取null的key和非null的key之分。感觉也没啥好讲的，随便看下源码就一目了然了。<br>基本思路：获取hash值，获取桶位置，桶中的链表，判断Entry的保存的hash值，key值使用相同，都一致返回value，否则返回null。</p>
<h2 id="2-5-remove-Object-key"><a href="#2-5-remove-Object-key" class="headerlink" title="2.5 remove(Object key)"></a>2.5 remove(Object key)</h2><p>remove方法的基本思路和get差不多，无非也就是获取对应key的value后进行链表中数据的删除罢了。。。就是移动指针进行删除，最后将删除的值返回出去。</p>
<h2 id="2-6-Set-lt-Map-Entry-lt-K-V-gt-gt-entrySet"><a href="#2-6-Set-lt-Map-Entry-lt-K-V-gt-gt-entrySet" class="headerlink" title="2.6 Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet()"></a><code>2.6 Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet()</code></h2><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> Set&lt;Map.Entry&lt;K,V&gt;&gt; entrySet0() &#123;</span><br><span class="line">    Set&lt;Map.Entry&lt;K,V&gt;&gt; es = entrySet;</span><br><span class="line">    <span class="keyword">return</span> es != <span class="keyword">null</span> ? es : (entrySet = <span class="keyword">new</span> EntrySet());</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
<p>这里返回的entrySet始终是一个实例，所以在调用HashMap的put和remove等方法后，会改变entrySet实例。<br>继续跟踪new EntrySet(), EntrySet这个类继承了AbstractSet类，实现了iterator()等方法，所以当我们调用iterator()的时候返回一个迭代器。<br>调用之后实际调用newEntryIterator()，返回new EntryIterator()。然后迭代的时候调用hasNext()和next()，当调用next()方法的时候实际调用nextEntry()，这里面的逻辑其实就跟一般的迭代相差不大。EntryIterator类是HashIterator的子类，调用EntryIterator类的next()方法其实是调用了父类中的nextEntry()方法，感觉有一种静态代理的感觉。</p>
<figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">private</span> <span class="keyword">abstract</span> <span class="class"><span class="keyword">class</span> <span class="title">HashIterator</span>&lt;<span class="title">E</span>&gt; <span class="keyword">implements</span> <span class="title">Iterator</span>&lt;<span class="title">E</span>&gt; </span>&#123;     </span><br><span class="line">     Entry&lt;K,V&gt; next;	<span class="comment">// next entry to return                     </span></span><br><span class="line">     <span class="keyword">int</span> expectedModCount;	<span class="comment">// For fast-fail                        </span></span><br><span class="line">     <span class="keyword">int</span> index;		<span class="comment">// current slot                                 </span></span><br><span class="line">     Entry&lt;K,V&gt; current;	<span class="comment">// current entry    </span></span><br><span class="line">     <span class="comment">// 初始化                     </span></span><br><span class="line">     HashIterator() &#123;                                                </span><br><span class="line">         expectedModCount = modCount;                                </span><br><span class="line">         <span class="keyword">if</span> (size &gt; <span class="number">0</span>) &#123; <span class="comment">// advance to first entry                   </span></span><br><span class="line">             Entry[] t = table;                                      </span><br><span class="line">             <span class="keyword">while</span> (index &lt; t.length &amp;&amp; (next = t[index++]) == <span class="keyword">null</span>) </span><br><span class="line">                 ;                                                   </span><br><span class="line">         &#125;                                                           </span><br><span class="line">     &#125;                                                               </span><br><span class="line">     <span class="comment">// 判断是否有下一个                                                           </span></span><br><span class="line">     <span class="function"><span class="keyword">public</span> <span class="keyword">final</span> <span class="keyword">boolean</span> <span class="title">hasNext</span><span class="params">()</span> </span>&#123;                                </span><br><span class="line">         <span class="keyword">return</span> next != <span class="keyword">null</span>;                                        </span><br><span class="line">     &#125;                                                               </span><br><span class="line">     <span class="comment">// 获取下一个元素                                                       </span></span><br><span class="line">     <span class="function"><span class="keyword">final</span> Entry&lt;K,V&gt; <span class="title">nextEntry</span><span class="params">()</span> </span>&#123;                                  </span><br><span class="line">         <span class="keyword">if</span> (modCount != expectedModCount)                           </span><br><span class="line">             <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();            </span><br><span class="line">         Entry&lt;K,V&gt; e = next;                                        </span><br><span class="line">         <span class="keyword">if</span> (e == <span class="keyword">null</span>)                                              </span><br><span class="line">             <span class="keyword">throw</span> <span class="keyword">new</span> NoSuchElementException();                     </span><br><span class="line">                                                                     </span><br><span class="line">         <span class="keyword">if</span> ((next = e.next) == <span class="keyword">null</span>) &#123;                              </span><br><span class="line">             Entry[] t = table;                                      </span><br><span class="line">             <span class="keyword">while</span> (index &lt; t.length &amp;&amp; (next = t[index++]) == <span class="keyword">null</span>) </span><br><span class="line">                 ;                                                   </span><br><span class="line">         &#125;                                                           </span><br><span class="line">         current = e;                                                    </span><br><span class="line">         <span class="keyword">return</span> e;                                                   </span><br><span class="line">     &#125;                                                               </span><br><span class="line">                                                               </span><br><span class="line">     <span class="function"><span class="keyword">public</span> <span class="keyword">void</span> <span class="title">remove</span><span class="params">()</span> </span>&#123;                                          </span><br><span class="line">         <span class="keyword">if</span> (current == <span class="keyword">null</span>)                                        </span><br><span class="line">             <span class="keyword">throw</span> <span class="keyword">new</span> IllegalStateException();                      </span><br><span class="line">         <span class="keyword">if</span> (modCount != expectedModCount)                           </span><br><span class="line">             <span class="keyword">throw</span> <span class="keyword">new</span> ConcurrentModificationException();            </span><br><span class="line">         Object k = current.key;                                     </span><br><span class="line">         current = <span class="keyword">null</span>;                                             </span><br><span class="line">         HashMap.<span class="keyword">this</span>.removeEntryForKey(k);                          </span><br><span class="line">         expectedModCount = modCount;                                </span><br><span class="line">     &#125;                                                               </span><br><span class="line">                                                                     </span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>
<h2 id="2-7-Set-lt-K-gt-keySet"><a href="#2-7-Set-lt-K-gt-keySet" class="headerlink" title="2.7 Set&lt;K&gt; keySet()"></a>2.7 <code>Set&lt;K&gt; keySet()</code></h2><p>熟悉上面的entrySet()方法之后，keySet()方法其实就是回去上面的Entry然后再返回一个key罢了，是基于entrySet()方法的一个实现。这里需要注意的是，keySet()返回的实例和entrySet()一样，也是只有一个实例，所以对HashMap的put，remove等操作之后，也会改变这个实例。</p>
<h2 id="2-8-杂鱼方法"><a href="#2-8-杂鱼方法" class="headerlink" title="2.8 杂鱼方法"></a>2.8 杂鱼方法</h2><p>剩余的size()，isEmpty()，containsKey(Object key)，containsValue(Object value)就不说了，实现也是比较简单的。。</p>
<h1 id="3-总结"><a href="#3-总结" class="headerlink" title="3. 总结"></a>3. 总结</h1><ol>
<li>总体上java1.6和1.7基本没什么大的差异，比较集合分析来看，1.7在实例的初始化上采用类似懒汉的方式，不是一开始就是初始化维护数据的数组的大小，而是在调用方法的时候进行初始化。其余就是一些算法上的优化吧。</li>
<li>学完HashMap，基本HashTable也就基本ok了，与HashTable的不同就不详细总结了，大家自行百度。。有几个说下：<ul>
<li>(1) HashTable大多数方法都是同步的，HashMap不是。</li>
<li>(2) HashMap支持空的key和空的value，HashTable不支持。</li>
<li>(3) HashMap没有了contains(Object o)方法</li>
</ul>
</li>
<li>一个比较好的消息就是学完HashMap之后，<code>HashSet类</code>基本上就不用看了，实现90%的代码采用了HashMap类的方法。。。HashSet其实就是将值存储在HashMap的key中，所以有用的代码100行都不到。。。。</li>
<li>最后读一读源码可以在理解是豁然开朗，大家加油。</li>
</ol>

        
    

    
</div>


                

                <!-- Post Comments -->
                
                    
    <div id="comment" style='padding:10px;' class="vcomment"></div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src="//unpkg.com/valine/dist/Valine.min.js"></script>
<script>
    var GUEST_INFO = ['nick','mail','link'];
    var guest_info = 'nick,mail,link'.split(',').filter(function(item){
        return GUEST_INFO.indexOf(item) > -1
    });
    var notify = 'false' == true;
    var verify = 'false' == true;
    new Valine({
        el: '.vcomment',
        notify: notify,
        verify: verify,
        appId: "vEOpfYrMUTPxez4tOTNQJv9A-gzGzoHsz",
        appKey: "qlbEzWd9EJ3vHa07eHpWPIVU",
        placeholder: "Just go go",
        pageSize:'10',
        avatar:'identicon',
        lang:'zh-cn'
    });
</script>

                
            </div>

            <!-- Post Prev & Next Nav -->
            <nav class="material-nav mdl-color-text--grey-50 mdl-cell mdl-cell--12-col">
    <!-- Prev Nav -->
    
        <a href="/2016/01/05/java/LinkedList源码分析/" id="post_nav-newer" class="prev-content">
            <button class="mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon mdl-color--white mdl-color-text--grey-900" role="presentation">
                <i class="material-icons">arrow_back</i>
            </button>
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
            新篇
        </a>
    

    <!-- Section Spacer -->
    <div class="section-spacer"></div>

    <!-- Next Nav -->
    
</nav>

        </div>
    </div>



                    
                        <!-- Overlay For Active Sidebar -->
<div class="sidebar-overlay"></div>

<!-- Material sidebar -->
<aside id="sidebar" class="sidebar sidebar-colored sidebar-fixed-left" role="navigation">
    <div id="sidebar-main">
        <!-- Sidebar Header -->
        <div class="sidebar-header header-cover" style="background-image: url(/img/sidebar_header.png);">
    <!-- Top bar -->
    <div class="top-bar"></div>

    <!-- Sidebar toggle button -->
    <button type="button" class="sidebar-toggle mdl-button mdl-js-button mdl-js-ripple-effect mdl-button--icon" style="display: initial;" data-upgraded=",MaterialButton,MaterialRipple">
        <i class="material-icons">clear_all</i>
        <span class="mdl-button__ripple-container">
            <span class="mdl-ripple">
            </span>
        </span>
    </button>

    <!-- Sidebar Avatar -->
    <div class="sidebar-image">
        <img src="/img/avatar.png" alt="xinwii's avatar">
    </div>

    <!-- Sidebar Email -->
    <a data-toggle="dropdown" class="sidebar-brand" href="#settings-dropdown">
        mestic@foxmail.com
        <b class="caret"></b>
    </a>
</div>


        <!-- Sidebar Navigation  -->
        <ul class="nav sidebar-nav">
    <!-- User dropdown  -->
    <li class="dropdown">
        <ul id="settings-dropdown" class="dropdown-menu">
            
                <li>
                    <a href="mailto:mestic@foxmail.com" target="_blank" title="Email Me">
                        
                            <i class="material-icons sidebar-material-icons sidebar-indent-left1pc-element">email</i>
                        
                        Email Me
                    </a>
                </li>
            
        </ul>
    </li>

    <!-- Homepage -->
    
        <li id="sidebar-first-li">
            <a href="/">
                
                    <i class="material-icons sidebar-material-icons">home</i>
                
                主页
            </a>
        </li>
        
    

    <!-- Archives  -->
    
        <li class="dropdown">
            <a href="#" class="ripple-effect dropdown-toggle" data-toggle="dropdown">
                
                    <i class="material-icons sidebar-material-icons">inbox</i>
                
                    归档
                <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
            <li>
                <a class="sidebar_archives-link" href="/archives/2018/06/">六月 2018<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/archives/2018/05/">五月 2018<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/archives/2018/04/">四月 2018<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2018/01/">一月 2018<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/08/">八月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/06/">六月 2017<span class="sidebar_archives-count">3</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/04/">四月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/03/">三月 2017<span class="sidebar_archives-count">8</span></a></li><li><a class="sidebar_archives-link" href="/archives/2017/01/">一月 2017<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2016/12/">十二月 2016<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/archives/2016/01/">一月 2016<span class="sidebar_archives-count">6</span></a>
            </ul>
        </li>
        
    

    <!-- Categories  -->
    
        <li class="dropdown">
            <a href="#" class="ripple-effect dropdown-toggle" data-toggle="dropdown">
                
                    <i class="material-icons sidebar-material-icons">chrome_reader_mode</i>
                
                分类
                <b class="caret"></b>
            </a>
            <ul class="dropdown-menu">
                <li>
                <a class="sidebar_archives-link" href="/categories/android/">android<span class="sidebar_archives-count">2</span></a></li><li><a class="sidebar_archives-link" href="/categories/java/">java<span class="sidebar_archives-count">18</span></a></li><li><a class="sidebar_archives-link" href="/categories/mysql/">mysql<span class="sidebar_archives-count">1</span></a></li><li><a class="sidebar_archives-link" href="/categories/weex/">weex<span class="sidebar_archives-count">1</span></a>
            </ul>
        </li>
        
            <li class="divider"></li>
        
    

    <!-- Pages  -->
    
        <li>
            <a href="/about" title="关于我">
                
                    <i class="material-icons sidebar-material-icons">person</i>
                
                关于我
            </a>
        </li>
        
    

    <!-- Article Number  -->
    
</ul>


        <!-- Sidebar Footer -->
        <!--
I'm glad you use this theme, the development is no so easy, I hope you can keep the copyright, I will thank you so much.
If you still want to delete the copyrights, could you still retain the first one? Which namely "Theme Material"
It will not impact the appearance and can give developers a lot of support :)

很高兴您使用并喜欢该主题，开发不易 十分谢谢与希望您可以保留一下版权声明。
如果您仍然想删除的话 能否只保留第一项呢？即 "Theme Material"
它不会影响美观并可以给开发者很大的支持和动力。 :)
-->

<!-- Sidebar Divider -->

    <div class="sidebar-divider"></div>


<!-- Theme Material -->

    <a href="https://github.com/viosey/hexo-theme-material"  class="sidebar-footer-text-a" target="_blank">
        <div class="sidebar-text mdl-button mdl-js-button mdl-js-ripple-effect sidebar-footer-text-div" data-upgraded=",MaterialButton,MaterialRipple">
            主题 - Material
            <span class="sidebar-badge badge-circle">i</span>
        </div>
    </a>


<!-- Help & Support -->
<!--

-->

<!-- Feedback -->
<!--

-->

<!-- About Theme -->
<!--

    <a href="https://blog.viosey.com/index.php/Material.html" target="_blank" class="sidebar-footer-text-a">
        <div class="sidebar-text mdl-button mdl-js-button mdl-js-ripple-effect sidebar-footer-text-div" data-upgraded=",MaterialButton,MaterialRipple">
             sidebar.about_theme
            <span class="mdl-button__ripple-container"><span class="mdl-ripple"></span></span></div>
    </a>

-->

    </div>

    <!-- Sidebar Image -->
    

</aside>

                    

                    
                        <!-- Footer Top Button -->
                        <div id="back-to-top" class="toTop-wrap">
    <a href="#top" class="toTop">
        <i class="material-icons footer_top-i">expand_less</i>
    </a>
</div>

                    

                    <!--Footer-->
<footer class="mdl-mini-footer" id="bottom">
    
        <!-- Paradox Footer Left Section -->
        <div class="mdl-mini-footer--left-section sns-list">
    <!-- Twitter -->
    

    <!-- Facebook -->
    

    <!-- Google + -->
    

    <!-- Weibo -->
    

    <!-- Instagram -->
    

    <!-- Tumblr -->
    

    <!-- Github -->
    
        <a href="https://github.com/xinwii" target="_blank">
            <button class="mdl-mini-footer--social-btn social-btn footer-sns-github">
                <span class="visuallyhidden">Github</span>
            </button><!--
     --></a>
    

    <!-- LinkedIn -->
    

    <!-- Zhihu -->
    

    <!-- Bilibili -->
    

    <!-- Telegram -->
    

    <!-- V2EX -->
    

    <!-- Segmentfault -->
    

    <p>Hosted by <a href="https://pages.coding.me" style="font-weight: bold">Coding Pages</a></p>
</div>


        <!--Copyright-->
        <div id="copyright">
            Copyright&nbsp;©&nbsp;<span year></span>&nbsp;android开发者
            
        </div>

        <!-- Paradox Footer Right Section -->

        <!--
        I am glad you use this theme, the development is no so easy, I hope you can keep the copyright.
        It will not impact the appearance and can give developers a lot of support :)

        很高兴您使用该主题，开发不易，希望您可以保留一下版权声明。
        它不会影响美观并可以给开发者很大的支持。 :)
        -->

        <div class="mdl-mini-footer--right-section">
            <div>
                <div class="footer-develop-div">Powered by Hexo</div>
                <div class="footer-develop-div">Theme - Material</div>
            </div>
        </div>
    
</footer>


                    <!-- Import JS File -->

    <script>lsloader.load("lazyload_js","/js/lazyload.min.js?1BcfzuNXqV+ntF6gq+5X3Q==", true)</script>



    <script>lsloader.load("js_js","/js/js.min.js?V/53wGualMuiPM3xoetD5Q==", true)</script>



    <script>lsloader.load("np_js","/js/nprogress.js?pl3Qhb9lvqR1FlyLUna1Yw==", true)</script>


<script type="text/ls-javascript" id="NProgress-script">
    NProgress.configure({
        showSpinner: true
    });
    NProgress.start();
    $('#nprogress .bar').css({
        'background': '#29d'
    });
    $('#nprogress .peg').css({
        'box-shadow': '0 0 10px #29d, 0 0 15px #29d'
    });
    $('#nprogress .spinner-icon').css({
        'border-top-color': '#29d',
        'border-left-color': '#29d'
    });
    setTimeout(function() {
        NProgress.done();
        $('.fade').removeClass('out');
    }, 800);
</script>





    <!-- Leancloud -->
    <script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script>
    <script>
        AV.initialize('vEOpfYrMUTPxez4tOTNQJv9A-gzGzoHsz', 'qlbEzWd9EJ3vHa07eHpWPIVU');
    </script>
    <script type="text/ls-javascript" id="leancloud-views-script">
    function showTime(Counter) {
        var query = new AV.Query(Counter);
        $('.leancloud-views_num').each(function() {
            var url = $(this).attr('id').trim();
            query.equalTo('url', url);
            query.find({
                success: function(results) {
                    if (results.length === 0) {
                        var content = '0 ' + $(document.getElementById(url)).text();
                        $(document.getElementById(url)).text(content);
                        return;
                    }
                    for (var i = 0; i < results.length; i++) {
                        var object = results[i];
                        var content = object.get('time') + ' ' + $(document.getElementById(url)).text();
                        $(document.getElementById(url)).text(content);
                    }
                },
                error: function(object, error) {
                    console.log('Error: ' + error.code + ' ' + error.message);
                }
            });
        });
    }

    function addCount(Counter) {
      var Counter = AV.Object.extend('Counter');
      url = $('.leancloud-views_num').attr('id').trim();
      title = $('.leancloud-views_num').attr('data-flag-title').trim();
      var query = new AV.Query(Counter);
      query.equalTo('url', url);
      query.find({
          success: function(results) {
            if (results.length > 0) {
                var counter = results[0];
                counter.fetchWhenSave(true);
                counter.increment('time');
                counter.save(null, {
                    success: function(counter) {
                        var content =  counter.get('time') + ' ' + $(document.getElementById(url)).text();
                        $(document.getElementById(url)).text(content);
                    },
                    error: function(counter, error) {
                        console.log('Failed to save Visitor num, with error message: ' + error.message);
                    }
                });
            } else {
              var newcounter = new Counter();
              newcounter.set('title', title);
              newcounter.set('url', url);
              newcounter.set('time', 1);
              newcounter.save(null, {
                  success: function(newcounter) {
                      console.log('newcounter.get(\'time\')='+newcounter.get('time'));
                      var content = newcounter.get('time') + ' ' + $(document.getElementById(url)).text();
                      $(document.getElementById(url)).text(content);
                  },
                  error: function(newcounter, error) {
                      console.log('Failed to create');
                  }
              });
            }
        },
        error: function(error) {
            console.log('Error:' + error.code + ' ' + error.message);
        }
      });
    }
    $(function() {
        var Counter = AV.Object.extend('Counter');
        if ($('.leancloud-views_num').length === 1) {
            addCount(Counter);
        } else if ($('.post-title-link').length > 1) {
            showTime(Counter);
        }
    });
</script>






   





<!-- UC Browser Compatible -->
<script>
	var agent = navigator.userAgent.toLowerCase();
	if(agent.indexOf('ucbrowser')>0) {
		document.write('<link rel="stylesheet" href="/css/uc.css">');
	   alert('由于 UC 浏览器使用极旧的内核，而本网站使用了一些新的特性。\n为了您能更好的浏览，推荐使用 Chrome 或 Firefox 浏览器。');
	}
</script>

<!-- Import prettify js  -->



<!-- Window Load -->
<!-- add class for prettify -->
<script type="text/ls-javascript" id="window-load">
    $(window).on('load', function() {
        // Post_Toc parent position fixed
        $('.post-toc-wrap').parent('.mdl-menu__container').css('position', 'fixed');
    });

    
    
</script>

<!-- MathJax Load-->


<!-- Bing Background -->


<script type="text/ls-javascript" id="lazy-load">
    // Offer LazyLoad
    queue.offer(function(){
        $('.lazy').lazyload({
            effect : 'show'
        });
    });

    // Start Queue
    $(document).ready(function(){
        setInterval(function(){
            queue.execNext();
        },200);
    });
</script>

<!-- Custom Footer -->



<script>
    var copyrightNow = new Date().getFullYear();
    var textContent = document.querySelector('span[year]')

    copyrightSince = 2015;
    if (copyrightSince === copyrightNow||copyrightSince === 0000) {
        textContent.textContent = copyrightNow
    } else {
        textContent.textContent = copyrightSince + ' - ' + copyrightNow
    }

    (function(){
        var scriptList = document.querySelectorAll('script[type="text/ls-javascript"]')

        for (var i = 0; i < scriptList.length; ++i) {
            var item = scriptList[i];
            lsloader.runInlineScript(item.id,item.id);
        }
    })()
console.log('\n %c © Material Theme | Version: 1.5.2 | https://github.com/viosey/hexo-theme-material %c \n', 'color:#455a64;background:#e0e0e0;padding:5px 0;border-top-left-radius:5px;border-bottom-left-radius:5px;', 'color:#455a64;background:#e0e0e0;padding:5px 0;border-top-right-radius:5px;border-bottom-right-radius:5px;');
</script>

                </main>
            </div>
        <script src="/live2dw/lib/L2Dwidget.min.js?0c58a1486de42ac6cc1c59c7d98ae887"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","model":{"scale":1,"hHeadPos":0.5,"vHeadPos":0.618,"jsonPath":"/live2dw/assets/z16.model.json"},"display":{"superSample":2,"width":150,"height":300,"position":"right","hOffset":0,"vOffset":-20},"mobile":{"show":true,"scale":0.1},"react":{"opacityDefault":0.7,"opacityOnHover":0.2}});</script></body>
    
</html>
